﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Threading;
using System.Windows;
using PairingMatrix.Common.Command;
using PairingMatrix.Common.Enum;
using PairingMatrix.Model;
using System.Linq;

namespace PairingMatrix.ViewModel
{
    public class PriorityCounterViewModel : ViewModelBase, IPriorityCounterViewModel
    {
        private readonly ObservableCollection<ProjectCardModel> _projectCards;
        private IEnumerable<ProjectCardModel> _projectCardsInThisLane;
        private readonly List<StoryStatus> applicableStatuses;

        public PriorityCounterViewModel(ObservableCollection<ProjectCardModel> projectCards, List<StoryStatus> applicableStatuses)
        {
            _projectCards = projectCards;
            _projectCardsInThisLane = projectCards.Where(p => p.IsCardVisibleInCurrentWall && applicableStatuses.Contains(p.DevStage) && p.IsMingleCard);
            this.applicableStatuses = applicableStatuses;
            _projectCards.CollectionChanged += _projectCards_CollectionChanged;
            _projectCards.ToList().ForEach(p => p.PropertyChanged += PriorityCounterViewModel_PropertyChanged);
            RecalculatePriorities();
        }

        void PriorityCounterViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Priority" || e.PropertyName == "IsCardVisibleInCurrentWall")
            {
                RecalculatePriorities();
            }
        }

        void _projectCards_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if(e.Action == NotifyCollectionChangedAction.Add)
            {
                ((ProjectCardModel)e.NewItems[0]).PropertyChanged += PriorityCounterViewModel_PropertyChanged;
            }
            RecalculatePriorities();
        }

        private void RecalculatePriorities()
        {
            Urgent = _projectCardsInThisLane.Count(p => p.Priority == 1 );
            High = _projectCardsInThisLane.ToList().Count(p => p.Priority == 2);
            Medium = _projectCardsInThisLane.ToList().Count(p => p.Priority == 3);
            Low = _projectCardsInThisLane.ToList().Count(p => p.Priority == 4);
        }

        private int _urgent;
        public int Urgent
        {
            get { return _urgent; }
            set
            {
                if (_urgent == value)
                    return;
                _urgent = value;
                OnPropertyChanged("Urgent");
            }
        }

        private int _high;
        public int High
        {
            get { return _high; }
            set
            {
                if (_high == value)
                    return;
                _high = value;
                OnPropertyChanged("High");
            }
        }

        private int _medium;
        public int Medium
        {
            get { return _medium; }
            set
            {
                if (_medium == value)
                    return;
                _medium = value;
                OnPropertyChanged("Medium");
            }
        }

        private int _low;
        public int Low
        {
            get { return _low; }
            set
            {
                if (_low == value)
                    return;
                _low = value;
                OnPropertyChanged("Low");
            }
        }

        private RelayCommand _arrangeCardsCommand;
        public RelayCommand ArrangeCardsCommand
        {
            get
            {
                return _arrangeCardsCommand ??
                       (_arrangeCardsCommand = new RelayCommand(param => ArrangeCards()));
            }
        }

        private void ArrangeCards()
        {
            var list = _projectCardsInThisLane.ToList();
            if (list.Count == 0)
                return; 

            var minY = list.Min(p => p.Position.Y);
            var initialPoint = list.First(p => p.Position.Y == minY).Position;
            list.Where(p => p.PrimaryCard == null) 
                .OrderBy(p => p.Priority).ToList()
                .ForEach(p =>
                                {
                                    p.Position = initialPoint;
                                    if (p.SecondaryProjectCards.Count > 0)
                                        initialPoint.Y += p.SecondaryProjectCards.Count*60 + 120;
                                    else
                                        initialPoint.Y += 120;
                                });
        }
    }
}